<?php

namespace app\common;
use app\api\model\Member as MemberModel;
use app\common\model\AccountAddress as AccountAddressModel;
use app\common\model\UserMoneyLog as UserMoneyLogModel;
use app\common\server\Sha256 as Sha256Model;
use think\cache\driver\Redis;
use app\common\model\RechargeOrder as RechargeOrderModel;
use app\api\model\BaseConfig as BaseConfigModel;
use think\facade\Db;
use IEXBase\TronAPI\Tron;

class Trc20
{
    protected static $usdt_contract_address = 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t';  //币种 合约地址 -> USDT
    public static $decimals = 6;//通证精度
    protected $base = 1000000;

    //生成地址
    public static function generate_address(){

        $url = 'http://trc.xinhuoio.com/api/task/add_address';

        //获取生成地址
        $client = new \GuzzleHttp\Client();
        $response = $client->request('GET', $url, [
            'headers' => [
                'accept' => 'application/json',
            ],
        ]);

        $info = json_decode($response->getBody(),true);
        if($info['code'] == 1){
            //private_key 秘钥
            //public_key 未知
            //address_hex 未知
            //address_base58 地址
            $sha256 = new Sha256Model();

            //获取钱包前缀
            $address_prefix = BaseConfigModel::config_data('address_prefix');
            //获取钱包总长度
            $wallet_address_length = BaseConfigModel::config_data('wallet_address_length');
            if($wallet_address_length > 0){ //有设定账号长度
                //账号长度减去前缀长度 = 剩余长度
                $random_num = bcsub($wallet_address_length,mb_strlen($address_prefix,'utf-8'));
            }else{
                //无设定账号长度 跟钱包长度一致
                $random_num = bcsub(mb_strlen($info['result']['address_base58'],'utf-8'),mb_strlen($address_prefix,'utf-8'));
            }
            if($random_num <= 0) $random_num = 18; //剩余长度小于0 默认改为18位

            $da = [
                'address'   =>  $address_prefix.$sha256->random($random_num),    //随机生成账号
                'real_address'   =>  $info['result']['address_base58'],
                'secret_key'   =>  $info['result']['private_key'],
                'public_key'   =>  $info['result']['public_key'],
                'address_hex'   =>  $info['result']['address_hex'],
                'type'  =>  1,
                'add_time'  =>  time()
            ];
            $res = AccountAddressModel::insertGetId($da);
        }
    }

    /**
     * 查询充值
     * @param $address 真实地址
     * @param $maid 实际地址id
     * @param $mid  用户ID
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public static function query_recharge($address){
        //读取改地址充值
        $url = "https://api.trongrid.io/v1/accounts/".$address."/transactions/trc20?limit=20&order_by=timestamp,desc&only_confirmed=true&only_to=true&contract_address=". self::$usdt_contract_address;

        $client = new \GuzzleHttp\Client();
        $response = $client->request('GET', $url, [
            'headers' => [
                'accept' => 'application/json',
            ],
        ]);
        $data = json_decode($response->getBody(),true);

        $redis = new Redis(config('cache.stores.redis'));

        if (isset($data['success']) && $data['success'] == true){
            foreach ($data['data'] as $datum) {
                $datum['block_timestamp'] = $datum['block_timestamp']/1000;

                //最新数据是否已充值过
                if($redis->get($datum['transaction_id']) == 1){
                    return ;
                }

                //查询数据是否存在
                $rechargeOrder  = RechargeOrderModel::getHash($datum['transaction_id']);
                if(!empty($rechargeOrder)){
                    return ;
                }
                //整理实际充值
                $amount = bcdiv($datum['value'], pow(10, self::$decimals), 6);

                $member = MemberModel::address($datum['to']);
                if(!empty($member)){

                    Db::startTrans();
                    try {
                        //记录充值数据
                        $id = RechargeOrderModel::add($member['id'],0,$datum['transaction_id'],$amount,$datum['to'],'USDT');
                        //充值
                        UserMoneyLogModel::change($member['id'],'usdt',$amount,'Wallet recharge');

                        Db::commit();
                    } catch (\Exception $e) {
                        // 回滚事务
                        Db::rollback();
                        return ;
                    }

                }

            }
        }

    }

    /**
     * 转账接口
     * @param string $from_address 转出地址
     * @param string $from_private_key 转出地址的密钥
     * @param string $to_address 转入地址
     * @param string $contractaddress 合约地址
     * @param float $num 转入数量
     */
    public function trx20_transfer($from_address, $from_private_key, string $to_address, float $num ,$contractaddress = 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t')
    {
        $tron = new Tron();

        $tron->setPrivateKey($from_private_key);
        $num = bcmul($num, 1000000);
        $abi = $this->getAbi();
        $abi = json_decode($abi, true);
        $b = $tron->getTransactionBuilder()->triggerSmartContract($abi, $tron->toHex('TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t'),
            'transfer', ['0' => $tron->toHex($to_address), '1' => $num], '100000000', $tron->toHex($from_address));
        //签名
        $c = $tron->signTransaction($b);

        //广播
        $d = $tron->sendRawTransaction($c);

        if (isset($d['result']) && isset($d['txid'])) {
            return json_encode(['error' => 0, 'msg' => '转账成功', 'data' => $d,'code'=>1]);
        } else {
            $message = pack("H*", $d['message']);
            return json_encode(['error' => 1, 'msg' => '转账失败；' . $message,'code'=>0]);
        }
    }


    /**
     * 查询trx20-u余额
     * @param $address 钱包地址
     * @param $contractaddress 币种合约
     * @return false|string
     * @throws \IEXBase\TronAPI\Exception\TronException
     */
    public function fTrc2UBalance($address,$contractaddress = 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t'){
        $tron = new Tron();

        //$address= input('get.address');
        //$address="TTFyT7Ds4NLDeVyZxfSaVuBC9KsFPdCtgL";
        $abi=json_decode(config('tron'),1);
        $a= $tron->getTransactionBuilder()->triggerConstantContract($abi,$tron->toHex($contractaddress),'balanceOf',['0'=>$tron->toHex($address)],$tron->toHex($address));

        $u_b=json_decode($a[0],1);//usdt余额

        //最终结果
        $u_balance=bcdiv($u_b, $this->base ,8);

        return $u_balance;
    }

}